package com.hd123.rumba.gwt.widget2.client.form;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasAllFocusHandlers;
import com.google.gwt.event.dom.client.HasAllKeyHandlers;
import com.google.gwt.event.dom.client.HasBlurHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.HasFocusHandlers;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusListener;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HasFocus;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.ListenerWrapper;
import com.google.gwt.user.client.ui.SourcesClickEvents;
import com.google.gwt.user.client.ui.Widget;
import com.hd123.rumba.gwt.widget2.client.tip.RTip;
import com.hd123.rumba.gwt.widget2.client.tip.RTipButton;

/**
 * 控件组，可以用来派生出诸如RadioGroup、CheckBoxGroup等。
 * 
 * @author LiQi
 * 
 */
@SuppressWarnings("deprecation")
public class RWidgetGroup extends RFieldComposite implements HasWidgets, HasFocus, Focusable,
    HasAllFocusHandlers, HasAllKeyHandlers, SourcesClickEvents, HasClickHandlers {

  /** 样式 */
  private static final String STYLENAME = "rb-WidgetGroup";
  private static final String STYLENAME_GRID = "rb-WidgetGroup-grid";

  /** 根面板 */
  private FlowPanel root;

  /** 摆放控件的表格 */
  private FlexTable grid;

  /** 布局方式：横向，所有单选按钮放在一行中，向右扩展 */
  public static final int LAYOUT_HORIZONTAL = 0;

  /** 布局方式：纵向，所有单选按钮放在一列中，向下扩展 */
  public static final int LAYOUT_VERTICAL = 1;

  /** 布局方式：网格，所有单选按钮放在一个表格中，表格的列数由gridColumnCount确定 */
  public static final int LAYOUT_GRID = 2;

  /** 布局方式，取值为LAYOUT_* */
  private int layout = LAYOUT_HORIZONTAL;

  /** layout==LAYOUT_GRID时表格的列数 */
  private int gridColumnCount = 2;

  /** 包含的控件 */
  private List widgets;

  /** 提示信息 */
  private RTip tip;

  /** 提示信息按钮 */
  private RTipButton tipButton;

  /** 所包含控件的事件处理 */
  private WidgetHandler widgetHandler;

  public RWidgetGroup() {
    super();

    widgets = new ArrayList();
    tip = new RTip();
    widgetHandler = new WidgetHandler();

    root = new FlowPanel();
    root.setStyleName(STYLENAME);

    grid = new FlexTable();
    grid.setStyleName(STYLENAME_GRID);
    grid.setCellPadding(0);
    grid.setCellSpacing(0);
    root.add(grid);

    initWidget(root);
  }

  /**
   * 布局方式，取值为LAYOUT_*，默认为LAYOUT_HORIZONTAL
   * 
   * @return
   */
  public int getLayout() {
    return layout;
  }

  /**
   * 设置布局方式，取值为LAYOUT_*，默认为LAYOUT_HORIZONTAL
   * 
   * @param layout
   */
  public void setLayout(int layout) {
    if (this.layout == layout)
      return;

    this.layout = layout;
    rebuild();
  }

  /**
   * layout==LAYOUT_GRID时表格的列数，默认为2。
   * 
   * @return
   */
  public int getGridColumnCount() {
    return gridColumnCount;
  }

  /**
   * 设置layout==LAYOUT_GRID时表格的列数，默认为2。
   * 
   * @param gridColumnCount
   */
  public void setGridColumnCount(int gridColumnCount) {
    if (this.gridColumnCount == gridColumnCount)
      return;

    this.gridColumnCount = gridColumnCount;
    rebuild();
  }

  /**
   * 每个控件的padding，默认为0。
   * 
   * @return
   */
  public int getWidgetPadding() {
    return grid.getCellPadding();
  }

  /**
   * 设置每个控件的padding，默认为0。
   * 
   * @param widgetPadding
   */
  public void setWidgetPadding(int widgetPadding) {
    grid.setCellPadding(widgetPadding);
  }

  /**
   * 添加一个控件
   * 
   * @param widget
   */
  public void add(Widget widget) {
    switch (layout) {
    case LAYOUT_HORIZONTAL:
      grid.setWidget(0, widgets.size(), widget);
      break;

    case LAYOUT_VERTICAL:
      grid.setWidget(widgets.size(), 0, widget);
      break;

    case LAYOUT_GRID:
      int row = widgets.size() / gridColumnCount;
      int col = widgets.size() - row * gridColumnCount;
      grid.setWidget(row, col, widget);
      break;
    }

    if (widget instanceof HasFocusHandlers)
      ((HasFocusHandlers) widget).addFocusHandler(widgetHandler);
    if (widget instanceof HasBlurHandlers)
      ((HasBlurHandlers) widget).addBlurHandler(widgetHandler);

    widgets.add(widget);
  }

  /**
   * 重新布局
   * 
   */
  private void rebuild() {
    // 清除已存在的控件
    for (int row = grid.getRowCount() - 1; row >= 0; row--)
      grid.removeRow(row);

    switch (layout) {
    case LAYOUT_HORIZONTAL:
      for (int i = 0; i < widgets.size(); i++)
        grid.setWidget(0, i, (Widget) widgets.get(i));
      break;

    case LAYOUT_VERTICAL:
      for (int i = 0; i < widgets.size(); i++)
        grid.setWidget(i, 0, (Widget) widgets.get(i));
      break;

    case LAYOUT_GRID:
      for (int i = 0; i < widgets.size(); i++) {
        int row = i / gridColumnCount;
        int col = i - row * gridColumnCount;
        grid.setWidget(row, col, (Widget) widgets.get(i));
      }
      break;
    }
  }

  /**
   * 清除所有控件
   * 
   */
  public void clear() {
    for (int row = grid.getRowCount() - 1; row >= 0; row--)
      grid.removeRow(row);
    widgets.clear();
  }

  /**
   * 枚举所有控件
   * 
   * @return
   */
  public Iterator iterator() {
    return grid.iterator();
  }

  /**
   * 删除控件
   * 
   * @param widget
   * @return
   */
  public boolean remove(Widget widget) {
    widgets.remove(widget);
    return grid.remove(widget);
  }

  public int getTabIndex() {
    if (widgets.size() > 0 && widgets.get(0) instanceof Focusable)
      return ((Focusable) widgets.get(0)).getTabIndex();
    else
      return 0;
  }

  public void setAccessKey(char key) {
    if (widgets.size() > 0 && widgets.get(0) instanceof Focusable)
      ((Focusable) widgets.get(0)).setAccessKey(key);
  }

  public void setFocus(boolean focused) {
    if (widgets.size() > 0 && widgets.get(0) instanceof Focusable)
      ((Focusable) widgets.get(0)).setFocus(focused);
  }

  public void setTabIndex(int index) {
    if (widgets.size() > 0 && widgets.get(0) instanceof Focusable)
      ((Focusable) widgets.get(0)).setTabIndex(index);
  }

  /**
   * @deprecated 请用{@link #addFocusHandler}和
   *             {@link #addBlurHandler}代替
   */
  @Deprecated
  public void addFocusListener(FocusListener listener) {
    ListenerWrapper.WrappedFocusListener.add(this, listener);
  }

  /**
   * @deprecated 请用{@link #addFocusHandler}和
   *             {@link #addBlurHandler}返回的
   *             {@link HandlerRegistration#removeHandler}代替
   */
  @Deprecated
  public void removeFocusListener(FocusListener listener) {
    ListenerWrapper.WrappedFocusListener.remove(this, listener);
  }

  public HandlerRegistration addFocusHandler(FocusHandler handler) {
    return addDomHandler(handler, FocusEvent.getType());
  }

  public HandlerRegistration addBlurHandler(BlurHandler handler) {
    return addDomHandler(handler, BlurEvent.getType());
  }

  /**
   * @deprecated 请用{@link #addKeyUpHandler}、
   *             {@link #addKeyDownHandler}和
   *             {@link #addKeyPressHandler} 代替
   */
  @Deprecated
  public void addKeyboardListener(KeyboardListener listener) {
    ListenerWrapper.WrappedKeyboardListener.add(this, listener);
  }

  /**
   * @deprecated 请用{@link #addKeyUpHandler}、
   *             {@link #addKeyDownHandler}和
   *             {@link #addKeyPressHandler}返回的
   *             {@link HandlerRegistration#removeHandler}代替
   */
  @Deprecated
  public void removeKeyboardListener(KeyboardListener listener) {
    ListenerWrapper.WrappedKeyboardListener.remove(this, listener);
  }

  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
    return addDomHandler(handler, KeyDownEvent.getType());
  }

  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
    return addDomHandler(handler, KeyUpEvent.getType());
  }

  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
    return addDomHandler(handler, KeyPressEvent.getType());
  }

  /**
   * @deprecated 请用{@link #addClickHandler}代替
   */
  @Deprecated
  public void addClickListener(ClickListener listener) {
    ListenerWrapper.WrappedClickListener.add(this, listener);
  }

  /**
   * @deprecated 请用{@link #addClickHandler}返回的
   *             {@link HandlerRegistration#removeHandler}代替
   */
  @Deprecated
  public void removeClickListener(ClickListener listener) {
    ListenerWrapper.WrappedClickListener.remove(this, listener);
  }

  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return addDomHandler(handler, ClickEvent.getType());
  }

  /**
   * 取得控件所包含的提示信息对象。
   * 
   * @return
   */
  public RTip getTip() {
    if (tipButton == null) {
      tipButton = new RTipButton();
      root.add(tipButton);
      tipButton.bind(tip);
    }
    return tip;
  }

  /**
   * 摆放控件的表格
   * 
   * @return
   */
  protected FlexTable getGrid() {
    return grid;
  }

  /**
   * 所包含控件的事件处理
   * 
   * @author LiQi
   * 
   */
  private class WidgetHandler implements FocusHandler, BlurHandler {

    public void onFocus(FocusEvent event) {
      RWidgetGroup.this.fireEvent(event);
    }

    public void onBlur(BlurEvent event) {
      RWidgetGroup.this.fireEvent(event);
    }
  }
}
